package com.seven.sso.config;

import com.alibaba.fastjson.JSON;
import com.seven.sso.service.Impl.UserDetailService;


import com.seven.utils.JWTUtil;
import com.seven.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author longlong
 * @date 2024/2/21 14:38
 * description
 */
@Configuration
public class securityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserDetailService UserDetailService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(UserDetailService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
//                todo 修改默认登录的提交路径
                .loginProcessingUrl("/sso/login")
//                .successForwardUrl("/success") //登录成功的跳转路径 必须是post
//                .failureForwardUrl("/errorlogin")
                .successHandler(successHandler())
//                .failureUrl("/errorlogin.html") //登录失败的跳转路径
                .failureHandler(failerHandler())
                .permitAll(); //放行
        //没有权限跳转的路径
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
        //禁用跨域伪造请求
        http.csrf().disable();
        //允许跨域
//        http.cors();
        //禁用其余所有请求
        http.authorizeRequests().anyRequest().authenticated();

    }
    //登录成功处理
    private AuthenticationSuccessHandler successHandler(){
        return new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                response.setCharacterEncoding("utf-8");
                Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
                List<String> promission = authorities.stream().map(item -> item.getAuthority()).collect(Collectors.toList());

                String token = JWTUtil.generateToken(authentication.getName(),promission);
                redisTemplate.opsForValue().set(token,"",24, TimeUnit.HOURS);
                PrintWriter writer = response.getWriter();
                writer.write(JSON.toJSONString(new Result(2000,"登录成功",token)));
                writer.flush();
                writer.close();
            }
        };
    }

    //登录失败处理
    private AuthenticationFailureHandler failerHandler(){
        return new AuthenticationFailureHandler(){

            @Override
            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                response.setCharacterEncoding("utf-8");
//                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.write(JSON.toJSONString(new Result(4001,"登录失败",null)));
                writer.flush();
                writer.close();
            }
        };
    }

    private AccessDeniedHandler  accessDeniedHandler(){
         return new AccessDeniedHandler(){

             @Override
             public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                 response.setCharacterEncoding("utf-8");
//                response.setContentType("application/json;charset=utf-8");
                 PrintWriter writer = response.getWriter();
                 writer.write(JSON.toJSONString(new Result(4003,"无权限，请联系管理员！！！",null)));
                 writer.flush();
                 writer.close();
             }
         };
     }

}
